package com.jwgf.queueprogramflash;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class HexBlock {
	private int baseAddr;
	private int offset;
	private byte[] data;
	// according to MCU's flash byte width per address.
	private int byteWidth = 2;
	private int nextAddr;

	public HexBlock(int baseAddr) {
		this.baseAddr = baseAddr;
	}

	private byte[] getDataSegment(byte[] line) {
		int len = line[0];
		byte[] data = new byte[len];
		System.arraycopy(line, 4, data, 0, len);
		return data;
	}

	private int getAddrSegment(byte[] line) {
		return ((line[1] & 0xff) << 8) | (line[2] & 0xff);
	}

	public void Add(byte[] line) {
		byte[] pureData = getDataSegment(line);
		if (data == null) {
			data = new byte[pureData.length];
			System.arraycopy(pureData, 0, data, 0, pureData.length);
			offset = getAddrSegment(line);
			nextAddr = getStartAddr() + pureData.length / byteWidth;
		} else {
			byte[] result = Arrays.copyOf(data, data.length + pureData.length);
			System.arraycopy(pureData, 0, result, data.length, pureData.length);
			data = result;
			nextAddr += pureData.length / byteWidth;
		}
	}

	public boolean checkContinuity(int addr) {
		if (data == null) {
			return true;
		} else {
			return nextAddr == addr;
		}
	}

	public int getStartAddr() {
		return baseAddr + offset;
	}

	public void setBaseAddr(int addr) {
		baseAddr = addr;
	}

	public int getBaseAddr() {
		return baseAddr;
	}

	public int getBlockSize() {
		if (data == null) {
			return 0;
		} else {
			return data.length;
		}
	}

	public byte[] getData() {
		return data;
	}

	public List<HexPage> splitPage(int maxSize) {
		List<HexPage> listPage = new ArrayList<HexPage>();
		int pageCnt = data.length % maxSize == 0 ? data.length / maxSize
				: data.length / maxSize + 1;
		for (int i = 0; i < pageCnt - 1; ++i) {
			HexPage page = new HexPage(getStartAddr() + maxSize * i / byteWidth);
			page.Add(data, maxSize * i, maxSize);
			listPage.add(page);
		}
		HexPage page = new HexPage(getStartAddr() + maxSize * (pageCnt - 1)
				/ byteWidth);
		int len = data.length % maxSize == 0 ? maxSize : data.length % maxSize;
		page.Add(data, maxSize * (pageCnt - 1), len);
		listPage.add(page);
		return listPage;
	}
}
